package org.vigor.lab.gateway.zuul.filter;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Strings;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.util.UrlPathHelper;
import org.vigor.lab.gateway.exception.AuthFailException;
import org.vigor.lab.gateway.jwt.JwtHelper;

import javax.servlet.http.HttpServletRequest;

/**
 * AuthZuulFilter
 * <p>
 * </p>
 *
 * @author Vigor Yuan
 */
public class AuthZuulFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    JwtHelper jwtHelper;

    private PathMatcher pathMatcher = new AntPathMatcher();

    private UrlPathHelper urlPathHelper = new UrlPathHelper();

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return 1;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String requestURI = urlPathHelper.getLookupPathForRequest(ctx.getRequest());
        logger.debug("requestURI[{}]", requestURI);
        return this.pathMatcher.match("/**/api/**", requestURI);
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest servletRequest = ctx.getRequest();
        String authorization = servletRequest.getHeader("Authorization");
        logger.debug("check authorization[{}]", authorization);
        if (Strings.isNullOrEmpty(authorization)) {
            throw AuthFailException.TOKEN_NONE("token is null");
        }

        String[] split = authorization.split(" ");
        if (Strings.isNullOrEmpty(split[0])) {
            logger.warn("token [{}] type null...", authorization);
            throw AuthFailException.TOKEN_ERROR("token type is null");
        } else if (!split[0].equals("Bearer")) {
            logger.warn("token [{}] type error...", authorization);
            throw AuthFailException.TOKEN_ERROR("token type error");
        }
        String token = split[1];
        try {
            Claims claims = jwtHelper.parseJWT(token);
            ctx.set("claims", claims);
            String claimsJson = JSON.toJSONString(claims);
            ctx.addZuulRequestHeader("claims", claimsJson);
            logger.debug("client[{}] pass", claimsJson);

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            throw AuthFailException.TOKEN_ERROR("token parse error " + e.getMessage());
        }

        return null;
    }
}
